# S3 and CloudFiles Screenshot and Upload Script
# Requires gawk curl xsel scrot openssl imagemagick

# This script uses OpenSSL to generate MD5 hases for filenames.
# These hashes are based on the file itself and not the timestamp.
# When all is said and done, this prevents users from systematically downloading your screenshots/uploads.

SCRIPTDIR=`dirname "$0"` # Where should screenshots be saved?

#################
# Configuration #
#################

UPLOADMETHOD="" # "s3" for Amazon S3, "cloudfiles" for RackSpace CloudFiles
LOGIN="" # S3 API Key or CloudFiles User
PASS="" # S3 API Secret or CloudFiles API Key
CONTAINER="" # Container or S3 Bucket where you want to store your uploads
BASEURL="" # Base URL - typically "https://s3.amazonaws.com/$CONTAINER" or your CF CDN URL

DROPSHADOW="" # true/false - Apply a dropshadow to screenshot?  Does *not* apply to file uploads.
DELETELOCAL="" # true/false - Delete the local SCREENSHOT after upload?  Doesn't apply to file uploads.

URLMETHOD="" # "long", "bitly", "isgd", or "tinyurl"
URL_APIU="" # API user for URL service (currently only needed for bit.ly)
URL_APIK="" # API key for URL service (again, currently only needed for bit.ly)

###################################################
###### START THE SCREENSHOT AND UPLOAD PROCESS ####
###################################################

# Make sure we have our ducks in a row
if [ "$UPLOADMETHOD" = "" ] || [ "$LOGIN" = "" ] || [ "$PASS" = "" ] || [ "$CONTAINER" = "" ] || [ "$BASEURL" = "" ]; then
	zenity --error --text "You fail at life.  Go back.  Check your settings.  Make sure everything is there.  Try again."
	exit
fi

# Get a UNIX timestamp
DATE=`date +%s`

# If a paramater (file) has been specified (e.g. dropped onto a Gnome panel shortcut), we'll upload it.
# If not, we'll take a screenshot and upload *that*
if [ "$1" = "" ]; then
	ACTION="screenshot"
	FILE_FULL="$SCRIPTDIR/$DATE.png"
	scrot -s $FILE_FULL
	FILE="`openssl md5 < $FILE_FULL`.png"
	if [ "$DROPSHADOW" = "true" ]; then
		convert $FILE_FULL -gravity northwest -background 'rgba(255,255,255,0)' -splice 10x10 \
		\( +clone -background gray -shadow 80x12-1-1 \) +swap -background none -mosaic +repage \
		\( +clone -background gray -shadow 80x12+5+5 \) +swap -background none -mosaic +repage $FILE_FULL
	fi
	else
		ACTION="upload"
		FILE_FULL="$1"
		if [ -f $FILE_FULL ]; then
			FILE="`openssl md5 < $FILE_FULL`.`echo "$FILE_FULL"|awk -F . '{print $NF}'`"
		else
			zenity --error --text "\"$FILE_FULL\" does not exist.  Script cannot continue."
			exit
		fi
fi

# Determine the MIME filetype based on the file extension
MIMETYPE="`file --mime-type $FILE_FULL | cut -d " " -f2`"
CLASSIFICATION=`echo $MIMETYPE | cut -d "/" -f1`

# Upload the file according to the specified upload method
if [ "$UPLOADMETHOD" = "s3" ]; then
	# Create policy file
	POLFILE="$SCRIPTDIR/POLFILE$DATE.tmp"
	echo { >> $POLFILE
	echo   \"expiration\": \"2015-06-15T12:00:00.000Z\", >> $POLFILE
	echo   \"conditions\": [ >> $POLFILE
	echo	 {\"acl\": \"public-read\"}, >> $POLFILE
	echo     {\"bucket\": \"$CONTAINER\" }, >> $POLFILE
	echo     [\"eq\", \"\$key\", \"$FILE\"], >> $POLFILE
	echo     [\"eq\", \"\$Content-Type\", \"$MIMETYPE\"] >> $POLFILE
	echo   ] >> $POLFILE
	echo } >> $POLFILE
	# Generate policy hash and signature
	POLICY="`base64 -w0 $POLFILE`"
	SIGNATURE="`base64 -w0 $POLFILE | openssl dgst -sha1 -hmac $PASS -binary | openssl base64`"
	# Upload the file
	curl \
	-F "key=$FILE" \
	-F "acl=public-read" \
	-F "Policy=$POLICY" \
	-F "AWSAccessKeyId=$LOGIN" \
	-F "Signature=$SIGNATURE" \
	-F "Content-Type=$MIMETYPE" \
	-F "file=@$FILE_FULL" \
	http://$CONTAINER.s3.amazonaws.com
	# Determine what the URL should be
	LONGURL="$BASEURL/$FILE"
	# Remove the temporary S3 policy file
	rm $POLFILE
elif [ "$UPLOADMETHOD" = "cloudfiles" ]; then
	# Connect to CloudFiles and get token for upload
	eval $(curl -s -X "GET" -D - \
	  -H "X-Auth-Key:$PASS" \
	  -H "X-Auth-User:$LOGIN" \
	  https://api.mosso.com/auth | gawk '$1=="X-Storage-Token:" { sub(/\r/,"",$2);printf("TOKEN=\"%s\"\n",$2); } 
	                                    $1=="X-Storage-Url:" { sub(/\r/,"",$2);printf("SURL=\"%s\"\n",$2) }
	                                    $1=="X-CDN-Management-Url:" { sub(/\r/,"",$2);printf("CDN=\"%s\"\n",$2) }')
	# Upload file
	curl -s -X "PUT" -T "$FILE_FULL"  \
	     -H "X-Auth-Token: $TOKEN" \
	     -H "Content-Type: $MIMETYPE" \
	     $SURL/$CONTAINER/$FILE
	# Determine what the URL should be
	LONGURL="$BASEURL/$FILE"
elif [ "$UPLOADMETHOD" = "imageshack" ]; then
	if [ "$CLASSIFICATION" = "image" ]; then
		OLDFILE="$FILE_FULL"
		FILE_FULL="`dirname $OLDFILE`/$FILE"
		mv $OLDFILE $FILE_FULL
		LONGURL=`curl -H Expect: -F fileupload="@$FILE_FULL" -F xml=yes -# "http://www.imageshack.us/index.php" | grep image_link | grep -o  http[^\<]*`
		mv $FILE_FULL $OLDFILE
		FILE_FULL="$OLDFILE"
	else
		zenity --error --text "Imageshack is an image hosting service.  You are trying to upload a \"$CLASSIFICATION\" file.  This simply cannot be done."
		exit
	fi
elif [ "$UPLOADMETHOD" = "imgur" ]; then
	if [ "$CLASSIFICATION" = "image" ]; then
		OLDFILE="$FILE_FULL"
		FILE_FULL="`dirname $OLDFILE`/$FILE"
		mv $OLDFILE $FILE_FULL
		LONGURL=`curl -s -F "image=@$FILE_FULL" -F "key=$PASS" http://imgur.com/api/upload.xml | grep -E -o "<original_image>(.)*</original_image>" | grep -E -o "http://i.imgur.com/[^<]*"`
		mv $FILE_FULL $OLDFILE
		FILE_FULL="$OLDFILE"
	else
		zenity --error --text "Imgur is an image hosting service.  You are trying to upload a \"$CLASSIFICATION\" file.  This simply cannot be done."
		exit
	fi
else
	zenity --error --text "This script is not configured to upload to \"$UPLOADMETHOD\".  Please select a valid option and try again."
	exit
fi

# Copy the URL to the clipboard
if [ "$URLMETHOD" = "long" ]; then
	URL="$LONGURL"
elif [ "$URLMETHOD" = "bitly" ]; then
	URL=`curl "http://api.bit.ly/v3/shorten?login=$URL_APIU&apiKey=$URL_APIK&format=txt&longUrl=$LONGURL"`
elif [ "$URLMETHOD" = "isgd" ]; then
	URL=`curl "http://is.gd/api.php?longurl=$LONGURL"`
elif [ "$URLMETHOD" = "vgd" ]; then
	URL=`curl "http://v.gd/create.php?format=simple&url=$LONGURL"`
elif [ "$URLMETHOD" = "tinyurl" ]; then
	URL=`curl "http://tinyurl.com/api-create.php?url=$LONGURL"`
else
	zenity --error --text "A valid URL method was not specified so no URL was copied to your clipboard."
fi
echo -n "$URL" | xsel --clipboard --input

# If we uploaded a screenshot and are configured to delete it, do so
if [ "$DELETELOCAL" = "true" ] && [ "$ACTION" = "screenshot" ]; then
	rm $FILE_FULL
fi
